const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const _ = require('lodash');
const path = require('path')
const fs = require('fs');
const joi = require('joi') // 表单验证
const { expressjwt: expressJWT } = require('express-jwt');
const config = require('./config');
const session = require('express-session'); // 引入session
const svgCaptcha = require("svg-captcha"); // 引入图形验证码
const multer = require("multer"); // 实现浏览器文件上传到服务器指定目录

// 创建服务器实例
const app = express()

app.use(express.static('uploads'))
app.use(bodyParser.urlencoded({ extended: false }))

// 跨域
app.use(cors())

// json
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
// 记录HTTP请求
app.use(morgan('dev'))
// session
// 启用session
app.use(session({
  resave: false,
  secret: 'secret',
  saveUninitialized: true,
}));

// 响应数据的中间件
app.use((req, res, next) => {
  // status=0为成功， status=500为失败，默认将status的值设置为500，方便处理失败的情况
  res.myMsg = (data, status = 500) => {
    if (status === 1) status = 500;
    if (status === 0 || status === 200) {
      res.status(status).send({
        // 状态
        status,
        // 状态描述，判断 err 是错误对象还是字符串
        message: '请求成功',
        data: data,
      })
    } else {
      res.status(status).send({
        // 状态
        status,
        // 状态描述，判断 err 是错误对象还是字符串
        message: data instanceof Error ? data.message : data,
        data: '',
      })
    }

  }
  next()
})

// 图形验证码中间件
app.get('/captcha', (req, res) => {
  // 创建验证码
  var captcha = svgCaptcha.create({
    color: true, // 验证码的字符是否有颜色，默认没有，如果设定了背景，则默认有
    inverse: true,// 反转颜色
    background: '#eee', // 验证码图片背景颜色
    width: 120, //  宽度
    height: 60, // 高度
    fontSize: 48, // 字体大小
    size: 4, // 验证码的长度
    noise: 3, // 干扰线条的数量
    ignoreChars: '0oO1ilI' // 验证码字符中排除 0o1i 这些较难识别的
  });
  req.session.captcha = captcha.text.toLowerCase(); // 保存验证码的内容（都转化为小写，以达到不区分大小写的目的）
  console.log('验证码', req.session.captcha)
  res.send(captcha.data);
})

// 在路由前注册解析token的中间件
app.use(expressJWT({ secret: config.jwtSecretKey, algorithms: config.algorithms })
  .unless({ path: [/^\/api\//] })
  .unless({ path: [/^\/uploads\//] })
  .unless({ path: [/^\/projectInfo\//], methods: ['GET'] })
  .unless({ path: [/^\//], methods: ['GET'] })
)

// 导入并注册用户路由模块
const userRouter = require('./router/user')
app.use('/api', userRouter)
// 导入并注册用户信息操作模块
const userinfoRouter = require('./router/userinfo')
app.use('/userinfo', userinfoRouter)
// 导入并注册项目分类操作模块
const projectCateRouter = require('./router/projectCate')
app.use('/projectCate', projectCateRouter)
// 导入并注册项目信息操作模块
const projectInfoRouter = require('./router/projectInfo')
app.use('/projectInfo', projectInfoRouter)
// 导入并注册项目评论操作模块
const projectCommentRouter = require('./router/projectComment')
app.use('/projectComment', projectCommentRouter)
// 导入并注册委托操作模块
const entrustInfoRouter = require('./router/entrust')
app.use('/entrustInfo', entrustInfoRouter)
// 导入并注册标签操作模块
const tabRouter = require('./router/tab')
app.use('/tab', tabRouter)
// 导入并注册文章操作模块
const postRouter = require('./router/postinfo')
app.use('/posts', postRouter)
// 导入并注册文章评论操作模块
const postCommentRouter = require('./router/postComment')
app.use('/postComment', postCommentRouter)
// 导入并注册项目点赞操作模块
const projectLikeRouter = require('./router/project_like')
app.use('/projectLike', projectLikeRouter)
// 导入并注册文章点赞操作模块
const postLikeRouter = require('./router/post_like')
app.use('/postLike', postLikeRouter)
// 导入并注册项目购买信息操作模块
const project_user_buyInfo = require('./router/project_user_buyInfo')
app.use('/projectBuyInfo', project_user_buyInfo)
// 导入并注册委托接取信息操作模块
const entrust_user_acceptinfo = require('./router/entrust_user_acceptinfo')
app.use('/entrustAcceptInfo', entrust_user_acceptinfo)



// 浏览器资源上传到服务器指定目录
// 指定目录
let objMulter = multer({ dest: "./public" }); // 实例化multer，传递的参数对象，dest表示上传文件的存储路径
app.use(objMulter.any()); // any表示任意类型的文件
// app.use(objMulter.image())//仅允许上传图片类型
app.use(express.static("./public")); // 将静态资源托管，这样才能在浏览器上直接访问预览图片或则html页面
const uploadimg = require('./router/uploadimg');
app.use('/api', uploadimg);

// 错误中间价
app.use((err, req, res, next) => {
  const err_log = `
        +---------------+-------------------------+
        错误名称：${err.name},\n
        错误信息：${err.message},\n
        错误时间：${new Date()},\n
        错误堆栈：${err.stack},\n
        +---------------+-------------------------+
    `
  fs.appendFile(path.join(__dirname, "error.log"), err_log, () => {
    // res.writeHead(500,{'Content-Type':'text/html;charset=utf-8'});
    // 数据验证失败
    if (err instanceof joi.ValidationError) return res.myMsg('数据验证失败')
    // 捕获身份认证失败
    if (err.name === 'UnauthorizedError') return res.myMsg('身份认证失败，请重新登录', 401)
    // 未知错误
    return res.send(err)
  });
  // res.myMsg(err)
})


const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`server is running at http://127.0.0.1:${port}`)
})
